﻿#ifndef DATASERIALPORT_H
#define DATASERIALPORT_H

#include <QObject>
#include <QSemaphore>
#include <QMutex>
#include <QRegExp>
#include <QSerialPort>
class QThread;
struct tagSerialPortInfo
{
    QString                     portName;
    qint32                      baudRate;
    QSerialPort::Directions     directions;
    QSerialPort::DataBits       dataBits;
    QSerialPort::FlowControl    flowControl;
    QSerialPort::Parity         parity;
    QSerialPort::StopBits       stopBits;

    tagSerialPortInfo()
    {
        directions = QSerialPort::AllDirections;
        dataBits = QSerialPort::Data8;
        flowControl = QSerialPort::NoFlowControl;
        parity = QSerialPort::NoParity;
        stopBits = QSerialPort::OneStop;
    }

    tagSerialPortInfo(QString name, qint32 rate):
        tagSerialPortInfo()
    {
        portName = name;
        baudRate = rate;
    }
};

class DataSerialPort : public QObject
{
    Q_OBJECT
public:
    explicit DataSerialPort();
    ~DataSerialPort();
    bool sendReciveData(const char * strCmd, qint64 leng, QByteArray& pstrReply);
    bool openPort(tagSerialPortInfo& cfg);
    bool isOpen() const;
    qint64 write(const QByteArray &byteArray);
    qint64 write(const char *data, qint64 maxSize = -1);
    void close();
    void clear();

protected:
    QString m_strComName;
    //========================
    QThread *m_pThread;
    QSerialPort *m_pCom;
    //=========================
    //write
    QMutex m_lockWrite;
    QSemaphore m_semWrite;
    QMutex m_lockWriteLen;
    qint64 m_iLen;
    //openCom
    QMutex m_lockSetCOM;
    QSemaphore m_semSetCOM;
    bool m_bOpen;
    //close
    QMutex m_lockClose;
    QSemaphore m_semClose;
    //clear
    QMutex m_lockClear;
    QSemaphore m_semClear;
    //=========================
    QMutex m_lockInBuffer;
    QString m_strInBuffer;
    QString m_strReply;

    QMutex m_lockExpect;
    QMutex m_lockEcho;
    QSemaphore m_semEcho;
private:
    bool m_bEchoFlag;
    mutable QMutex m_lockEchoFlag;
    void setEchoFlag(bool b)
    {
        QMutexLocker lk(&m_lockEchoFlag);
        m_bEchoFlag = b;
    }
    bool getEchoFlag() const
    {
        QMutexLocker lk(&m_lockEchoFlag);
        return m_bEchoFlag;
    }

signals:
    void sigCatchException(QString);
    void sigDataReady(QByteArray);
    void sigWrite(const char *, qint64);
    void sigSetCOM(tagSerialPortInfo);
    void sigClose();
    void sigClear();
private slots:
    void slotDataReady();
    void slotWrite(const char *pch, qint64);
    void slotClose();
    void slotClear();
    void slotSetCOM(tagSerialPortInfo cfg);
};

#endif // DATASERIALPORT_H
